<template>
  <section aria-labelledby="products-heading" class="pt-6 flex-1">
    <div class="grid grid-cols-1 gap-x-8 gap-y-10 lg:grid-cols-4">
      <!-- Filters -->
      <form class="hidden lg:block">
        <h3 class="sr-only">Categories</h3>
        <ul role="list" class="border-gray-200 pb-6 text-sm font-medium text-gray-900 h-168 overflow-auto">
          <li v-for="request in requestStore.requestList" :key="request.key"
            :class="['hover:bg-blue-200 p-1 hover:cursor-pointer', { 'bg-blue-200': request.key === requestStore.currentRequest?.key }]"
            @click="onRequestItemClick(request)">
            <a :href="request.href">{{ request.name }}</a>
          </li>
        </ul>
      </form>

      <!-- Product grid -->
      <div class="lg:col-span-3">
        <div class="flex items-center justify-end mb-2">
          <Menu as="div" class="relative inline-block text-left">
            <div>
              <MenuButton class="group inline-flex justify-center text-sm font-medium text-gray-700 hover:text-gray-900">
                其他操作
                <ChevronDownIcon class="-mr-1 ml-1 h-5 w-5 flex-shrink-0 text-gray-400 group-hover:text-gray-500"
                  aria-hidden="true" />
              </MenuButton>
            </div>

            <transition enter-active-class="transition ease-out duration-100"
              enter-from-class="transform opacity-0 scale-95" enter-to-class="transform opacity-100 scale-100"
              leave-active-class="transition ease-in duration-75" leave-from-class="transform opacity-100 scale-100"
              leave-to-class="transform opacity-0 scale-95">
              <MenuItems
                class="absolute right-0 z-10 mt-2 w-40 origin-top-right rounded-md bg-white shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none">
                <div class="py-1">
                  <MenuItem v-for="option in actionOptions" :key="option.name" v-slot="{ active }" @click="option.fn">
                  <span
                    :class="[option.current ? 'font-medium text-gray-900' : 'text-gray-500', active ? 'bg-gray-100' : '', 'block px-4 py-2 text-sm hover:cursor-pointer']">
                    {{ option.name }}
                  </span>
                  </MenuItem>
                </div>
              </MenuItems>
            </transition>
          </Menu>
          <div class="flex">
            <LButton class="ml-2" @click="handleReply">重放</LButton>
            <PayloadEditor class="ml-2" />
            <Dialog v-model:visible="visible" class="ml-2" btn-content="存储当前请求" title="存储当前请求" @cancel="visible = false"
              @confirm="onStorageDialogOk">
              <LForm :model="cacheRequestState" v-model:context="formContext">
                <LFormItem label="请求别名" prop="name">
                  <LInput type="text" v-model:value="cacheRequestState.name" placeholder="请输入请求别名" />
                </LFormItem>
              </LForm>
            </Dialog>
          </div>
        </div>
        <Disclosure as="nav" v-slot="{ open }">
          <div class="mx-auto max-w-7xl">
            <div class="relative flex h-16 items-center justify-between">
              <div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
                <!-- Mobile menu button-->
                <DisclosureButton
                  class="inline-flex items-center justify-center rounded-md p-2 text-gray-400 hover:bg-gray-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white">
                  <span class="sr-only">Open main menu</span>
                  <Bars3Icon v-if="!open" class="block h-6 w-6" aria-hidden="true" />
                  <XMarkIcon v-else class="block h-6 w-6" aria-hidden="true" />
                </DisclosureButton>
              </div>
              <div class="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
                <div class="hidden sm:block min-w-full">
                  <div class="flex space-x-4">
                    <LTab :tabs="tabs">
                      <TabPanel :class="tabPanelCls">
                        <Headers :headers="headers" />
                      </TabPanel>
                      <TabPanel :class="tabPanelCls">
                        <PayloadView :jsonObj="payloadJsonObj" />
                      </TabPanel>
                      <TabPanel :class="tabPanelCls">
                        <ResponsePreview :jsonObj="state.responseJsonObj" />
                      </TabPanel>
                    </LTab>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </Disclosure>
      </div>
    </div>
  </section>
  <CacheRequestList v-model:visible="cacheRequestListVisible" />
</template>
  
<script setup>
import {
  Disclosure,
  DisclosureButton,
  TabPanel,
  Menu,
  MenuButton,
  MenuItem,
  MenuItems,
} from "@headlessui/vue";
import { Bars3Icon, XMarkIcon } from "@heroicons/vue/24/outline";
import { Headers, PayloadView, ResponsePreview, LTab, Dialog, PayloadEditor, LInput, LForm, LFormItem, CacheRequestList, LMessage  } from "@/components";
import { useRequestStore } from "@/store/state/request-store";
import { parseParams } from "@/utils/request-util";
import { analysisResponse } from "@/utils/response-util.js";

import { ref, computed, reactive, watch } from "vue";
import { ChevronDownIcon } from "@heroicons/vue/20/solid";
import { repaly, copyAsFetch, copyPayloadAsJson } from "@/utils/request-util";
import { copyResponseAsJson } from "@/utils/response-util.js";
import { useChromeStorage } from "@/utils/chrome-storage.js";

const requestStore = useRequestStore();
const state = reactive({});

const tabPanelCls = [
  "rounded-xl bg-white p-3",
  "ring-white ring-opacity-60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2",
];

const tabs = [
  { title: "Headers" },
  { title: "Payload" },
  { title: "Preview" },
];

function parseItems(request) {
  if (!request) return;
  const keyMap = {
    "Request URL": request.plainUrl,
    "Request Method": request.request.method,
    "Request Code": request.response.status,
    "Remote Address": request.serverIPAddress,
  };
  return Object.entries(keyMap).map(([key, value]) => ({
    name: key,
    value,
  }));
}

const headers = computed(() => {
  if (!requestStore.currentRequest) return;
  return [
    {
      id: "general",
      title: "General",
      items: parseItems(requestStore.currentRequest),
    },
    {
      id: "request",
      title: "Request",
      items: requestStore.currentRequest.request.headers,
    },
    {
      id: "response",
      title: "Response",
      items: requestStore.currentRequest.response.headers,
    },
  ];
});

const payloadJsonObj = computed(() => {
  return parseParams(requestStore.currentRequest);
});

state.responseJsonObj = null;
watch(() => requestStore.currentRequest, (val) => {
  analysisResponse(val, state, "responseJsonObj");
});

const chromeStorage = useChromeStorage();

const cacheRequestListVisible = ref(false);
const actionOptions = [
  { name: "复制fetch函数", current: false, fn: () => { copyAsFetch(requestStore.currentRequest); } },
  { name: "复制payload", current: false, fn: () => { copyPayloadAsJson(requestStore.currentRequest); } },
  { name: "复制response", current: false, fn: () => { copyResponseAsJson(requestStore.currentRequest); } },
  { name: "清空存储库", current: false, fn: () => { chromeStorage.clear(); } },
  { name: "请求存储库", current: false, fn: () => { cacheRequestListVisible.value = true; } },
  { name: "清空请求列表", current: false, fn: () => { requestStore.clear(); } },
];

const visible = ref(false);

const onRequestItemClick = (item) => {
  requestStore.setCurrentRequest(item);
};
const handleReply = () => {
  if (requestStore.currentRequest) {
    repaly(requestStore.currentRequest);
    LMessage.success("重放成功");
  }
};

// 表单验证逻辑
const cacheRequestState = reactive({
  name: "",
});
const formContext = ref();
const onStorageDialogOk = () => {
  formContext.value.validate((flag, props) => {
    if (flag) {
      const { currentRequest } = requestStore;
      if (chromeStorage && currentRequest) {
        chromeStorage.put(cacheRequestState.name, currentRequest);
      }
      visible.value = false;
    } else {
      props?.forEach(() => {
        LMessage.error("请填写完整必填项");
      });
    }
  });
};
</script>